package com.jmcgg.freesky.common.dao;

import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;

import org.apache.log4j.Logger;

public class JPAUtil<T> {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger.getLogger(JPAUtil.class);

	private String jpaUnitName = "jmcggDB";
	private boolean isUpdated = false;
	private static EntityManagerFactory emf = null;
	private EntityManager em = null;
	private Class<T> persistentClass;

	public Class<T> getPersistentClass() {
		return persistentClass;
	}

	@SuppressWarnings("unchecked")
	public JPAUtil() {
		this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
	}

	public String getJpaUnitName() {
		return jpaUnitName;
	}

	public void setJpaUnitName(String jpaUnitName) {
		this.jpaUnitName = jpaUnitName;
		isUpdated = true;
	}

	public void init() {
		try {
			if (isUpdated) {
				isUpdated = false;
				emf = Persistence.createEntityManagerFactory(jpaUnitName);
				em = emf.createEntityManager();
			} else {
				if (emf == null)
					emf = Persistence.createEntityManagerFactory(jpaUnitName);
				if (em == null)
					em = emf.createEntityManager();
			}
		} catch (Exception ex) {
			logger.error("init()", ex);
		}
	}

	public boolean persist(T t) {
		init();
		try {
			em.getTransaction().begin();
			em.persist(t);
			em.getTransaction().commit();
			return true;
		} catch (Exception ex) {
			if (em.getTransaction().isActive())
				em.getTransaction().rollback();
			logger.error("persist(T)", ex);
			return false;
		}
	}

	public T merge(T t) {
		init();
		T ret = t;
		try {
			em.getTransaction().begin();
			ret = em.merge(t);
			em.getTransaction().commit();
		} catch (Exception ex) {
			if (em.getTransaction().isActive())
				em.getTransaction().rollback();
			logger.error("merge(T)", ex);
		}
		return ret;
	}

	public boolean remove(String fsId) {
		init();
		try {
			em.getTransaction().begin();
			T t = em.find(this.getPersistentClass(), fsId);
			em.remove(t);
			em.getTransaction().commit();
			return true;
		} catch (Exception ex) {
			if (em.getTransaction().isActive())
				em.getTransaction().rollback();
			logger.error("merge(T)", ex);
			return false;
		}
	}

	public T find(String fsId) {
		return (T) em.find(this.getPersistentClass(), fsId);
	}

	@SuppressWarnings("unchecked")
	public List<T> listAll(String queryName) {
		Query query = em.createNamedQuery(queryName);
		List<T> list = query.getResultList();
		return list;
	}

}
